package main;

import java.awt.Point;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;

import main.NMFTestProcessFixedR.SummaryInfo;
import nmf.NMFTool;
import nmf.NMFTool.Results;
import nmf.TitleFeatureNMFTool;

import org.ejml.simple.SimpleMatrix;

import svm.matrixToFile;
import svm.run_svm;
import utils.ClassificationUtil;

public class NMFRandomTestProcess extends Thread {
   public ArrayList<String> fileNames;
   public List<NMFTool> nmfTools;
   int rValue, trainingSetSize, numRepeatTimes;
   //X is number classified correctly
   //Y is total number
   HashMap<NMFTool, Point> map = new HashMap<NMFTool, Point>();
   public static ArrayList<Integer> rValues;
   public static String breakRegEx = "[.[^a-zA-Z]]";
   
   public synchronized HashMap<NMFTool, Point> getMap() {
      return map;
   }
   
   public NMFRandomTestProcess(final ArrayList<String> fileNames,
         final List<NMFTool> nmfTool, final ArrayList<Integer> rValues, final int trainingSetSize, final int numRepeatTimes) {
      this.fileNames = fileNames;
      this.nmfTools = nmfTool;
      NMFRandomTestProcess.rValues = rValues;
      this.trainingSetSize = trainingSetSize;
      this.numRepeatTimes = numRepeatTimes;
   }
   
   /**
    * Fills out a HashMap with the Shit we need.
    */
   @Override
   public synchronized void run() {
      try {
         //Best - 0
         //Average - 1
         //Worst   - 2
         final SummaryInfo[][][] summaries = new SummaryInfo[rValues.size()][numRepeatTimes][fileNames.size()];
         
         for (int currentDocCol = 0; currentDocCol < fileNames.size(); currentDocCol++) {
            final int[] actualClass = ReutersTest.classifications(fileNames.get(currentDocCol));
            
            final String[] fileNamesWorkAround = new String[1];
            fileNamesWorkAround[0] = fileNames.get(currentDocCol);
            for (NMFTool nmfTool : this.nmfTools) {
               double averageTime = System.nanoTime();
               final SimpleMatrix V = ClassificationUtil.getPreProcessedMatrix(fileNamesWorkAround, nmfTool instanceof TitleFeatureNMFTool);
               
               final int[] trainClass = new int[trainingSetSize];
               
               for (int i = 0; i < trainClass.length; i++) {
                  trainClass[i] = actualClass[i];
               }
               
               //loop over number of times we want simple to be repeated.
               for (int repeatNum = 0; repeatNum < numRepeatTimes; repeatNum++) {
                  for (int innerDimIndx = 0; innerDimIndx < rValues.size(); innerDimIndx++) {
                     rValue = rValues.get(innerDimIndx);
                     
                     final Results res = nmfTool.factor(V, rValue, trainClass);
                     final SimpleMatrix m_train_nmf = res.H.extractMatrix(0, res.H.numRows(), 0, trainClass.length);
                     
                     ReutersTest.write_file("src/svm/matrix_file_nmf", res.H.transpose());
                     ReutersTest.write_file("src/svm/matrix_file_train_nmf", m_train_nmf.transpose());
                     
                     final matrixToFile mft = new matrixToFile("src/svm/matrix_file_train_nmf", true, trainClass);
                     final matrixToFile mfc = new matrixToFile("src/svm/matrix_file_nmf", false, actualClass);
                     final run_svm svm = new run_svm("svmTrain", "svmFile", "svmOut");
                     
                     final FileInputStream in = new FileInputStream(new File("svmOut"));
                     final Scanner sc = new Scanner(in);
                     double currentClass;
                     //System.out.println("Classifications from SVM with factoring: \n");
                     int totalCorrect = 0;
                     int totalDocs = 0;
                     
                     for (int i = 0; sc.hasNext(); i++) {
                        currentClass = sc.nextDouble();
                        totalDocs++;
                        if (i == actualClass.length) {
                           System.out.println("Uh oh.");
                        }
                        if (currentClass == actualClass[i]) {
                           totalCorrect++;
                        }
                        //                     System.out.println(currentClass + " " + actualClass[i]);
                     }
                     //System.out.println("\n");
                     mfc.deleteFiles();
                     mft.deleteFiles();
                     svm.deleteFiles();
                     
                     summaries[innerDimIndx][repeatNum][currentDocCol] = new SummaryInfo(nmfTool.toString(), rValue, totalCorrect, totalDocs);
                  }
               }
               averageTime = (System.nanoTime() - averageTime) / 25;
               System.out.println("The average time for " + nmfTool + ": " + averageTime / 1000000000);
               
               /*            double totalCorrect = 0, totalDocs = 0;
                           for (int innerDim = 0; innerDim < rValues.size(); innerDim++) {
                              
                                 SummaryInfo acrossDocumentSummary = new SummaryInfo();
                                 acrossDocumentSummary.rValue = summaries[innerDim][toolNum][0].rValue;
                                 acrossDocumentSummary.nmfTool = nmfTools.get(toolNum).toString();
                                 for (int currentDocCol = 0; currentDocCol < fileNames.size(); currentDocCol++) {
                                    acrossDocumentSummary.numberOfDocumentsClassifiedCorrectly += summaries[innerDim][toolNum][currentDocCol].numberOfDocumentsClassifiedCorrectly;
                                    acrossDocumentSummary.totalNumberOfDocuments += summaries[innerDim][toolNum][currentDocCol].totalNumberOfDocuments;
                                 }
                                 totalCorrect += acrossDocumentSummary.numberOfDocumentsClassifiedCorrectly;
                                 totalDocs += acrossDocumentSummary.totalNumberOfDocuments;
                                 acrossDocumentSummary.printSummaryInfo();
                              }
                           if (nmfTools.size() == 1) 
                              System.out.println("Average Accuracy: " + totalCorrect / totalDocs);
                        System.out.println("Training Set Size: " + trainingSetSize);*/
               ClassificationUtil.writeToCSVRandom(summaries, "outPut//" + nmfTool + "_" + fileNames.size() + "_currentRun.csv");
               //         ClassificationUtil.writeToCSV(summaries, "outPut//" + nmfTool.toString() +"_"+ fileNames.size() + "_currentRun.csv");
            }
         }
         System.out.println("Simple Harvesting Complete.");
      }
      catch (final Exception e) {
         System.out.println("NMF Process Failed.\n");
         e.printStackTrace();
      }
   }
}
